package com.zhouxiaoge.解释器模式;

import java.util.Map;
import java.util.Stack;

/**
 * @author 周小哥
 * @date 2021年09月30日 17点38分
 */
public class Calculator {

    private final Expression expression;

    public Calculator(String expStr) {
        Stack<Expression> stack = new Stack<>();
        Stack<Expression> stack2 = new Stack<>();


        Expression left;
        Expression right;

        char[] chars = expStr.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            switch (chars[i]) {
                case '*':
                    if (stack.empty()) {
                        left = new VarExpression(String.valueOf(chars[--i]));
                    } else {
                        left = stack.pop();
                    }
                    right = new VarExpression(String.valueOf(chars[++i]));
                    stack.push(new MultiplyExpression(left, right));
                    break;
                case '/':
                    if (stack.empty()) {
                        left = new VarExpression(String.valueOf(chars[--i]));
                    } else {
                        left = stack.pop();
                    }
                    right = new VarExpression(String.valueOf(chars[++i]));
                    stack.push(new DivisionExpression(left, right));
                    break;
                case '+':
                case '-':
                    stack.push(new OperatorExpression(String.valueOf(chars[i])));
                    break;
                default:
                    stack.push(new VarExpression(String.valueOf(chars[i])));
                    break;
            }
        }

        for (int i = 0; i < stack.size(); i++) {
            Expression expression = stack.elementAt(i);
            if (expression instanceof OperatorExpression) {
                left = stack2.pop();
                OperatorExpression operatorExpression = (OperatorExpression) expression;
                String operator = String.valueOf(operatorExpression.getOperator());
                if ("-".equals(operator)) {
                    right = stack.elementAt(++i);
                    stack2.push(new SubExpression(left, right));
                } else {
                    right = stack.elementAt(++i);
                    stack2.push(new AddExpression(left, right));
                }
            } else {
                stack2.push(expression);
            }
        }

        expression = stack2.pop();
    }

    public int run(Map<String, Integer> var) {
        return expression.interpreter(var);
    }
}
